package ram;

//definition of an instruction
//
//g++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1 on
//Linux 2.6.31-23-generic 
//
//Editor:  tabstop=2, cols=80
//
//5/11 - add constructors to Instruction, KS
//5/11 - added MUL and JMZ, KS
//5/27/12 - ported to java, JL
//
public class Instruction {

	public enum OPCODES {
		// All OPCODES plus ILL, which is an illegal instruction
		ILL, LDA, LDI, STA, STI, ADD, SUB, MUL, JMP, JMI, JMZ, JMN, CAL, HLT;  
	}

	// Indicates where the stack pointer is
	protected static final int SP=0;
		
	private OPCODES opcode = OPCODES.ILL;
	private int operand = 0;
	private boolean valid = true;
	
	public Instruction( OPCODES code ) {
		setOpcode(code);
	}
	
	public Instruction( OPCODES code, int op ) {
		setOpcode(code);
		setOperand(op);
	}

	public Instruction(String code, String op) {

		if( code.equals("ILL") ) {
			opcode = OPCODES.ILL;
		} else if( code.equals( "LDA") ) {
			opcode = OPCODES.LDA;
		} else if( code.equals( "LDI") ) {
			opcode = OPCODES.LDI;
		} else if( code.equals( "STA") ) {
			opcode = OPCODES.STA;
		} else if( code.equals( "STI") ) {
			opcode = OPCODES.STI;
		} else if( code.equals( "ADD") ) {
			opcode = OPCODES.ADD;
		} else if( code.equals( "SUB") ) {
			opcode = OPCODES.SUB;
		} else if( code.equals( "MUL") ) {
			opcode = OPCODES.MUL;
		} else if( code.equals( "JMP") ) {
			opcode = OPCODES.JMP;
		} else if( code.equals( "JMI") ) {
			opcode = OPCODES.JMI;
		} else if( code.equals( "JMZ") ) {
			opcode = OPCODES.JMZ;
		} else if( code.equals( "JMN") ) {
			opcode = OPCODES.JMN;
		} else if( code.equals( "CAL") ) {
			opcode = OPCODES.CAL;
		} else if( code.equals( "HLT") ) {
			opcode = OPCODES.HLT;
		} else {
			valid = false;
		}

		// Everything but HLT or ILL needs an operand
		if( opcode != OPCODES.HLT && opcode != OPCODES.ILL ) {
			try {
				operand = Integer.parseInt(op);
			} catch( NumberFormatException e ) {
				valid = false;
			}
		}
	}

	protected OPCODES getOpcode() {
		return opcode;
	}

	private void setOpcode(OPCODES opcode) {
		this.opcode = opcode;
	}

	protected int getOperand() {
		return operand;
	}

	private void setOperand(int operand) {
		this.operand = operand;
	}
	
	public boolean isValid() {
		return valid;
	}
}
